/*
*************************************************************
 *@Copyright (C), 2016-2020 smartlinkMicro. Co., Ltd.  All rights reserved.
 *@Filename:
 *@Complier:
 *@Target OS:   NONE
 *@Target HW:   SL2x23
 *@Author:      htyi
 *@Version :    V1.0.0
 *@Date:        2017.8
 *@Description:
 *@History:
 *@    <author>     <time>     <version >   <desc>
*************************************************************
*/
#include <string.h>
#include <stdint.h>
#include "emv_if.h"
#include "sl2x23.h"
// #include "dwt/bsp_dwt_delay.h"   

// #include "systick/bsp_systick.h"

#include "los_task.h"
#include "lz_hardware.h"

#if defined IIC_Mode
    // #include "iic/bsp_iic.h"
    #include "bsp_I2C.h"
#else
    // #include "spi/bsp_spi.h"
#endif

#if defined IIC_Mode

#define SL2x23_DEV_ADDRESS  0x28

//通过IO将R8,R9配置成下拉
void SL2x23_R8R9_Config(void)
{
    // GPIO_InitTypeDef  GPIO_R8R9_InitStructure;

    // RCC_APB2PeriphClockCmd(SL2x23_GPIO_R8_CLK | SL2x23_GPIO_R9_CLK, ENABLE);

    // /* 配置 R8 */
    // GPIO_R8R9_InitStructure.GPIO_Pin = SL2x23_GPIO_R8_PIN;
    // GPIO_R8R9_InitStructure.GPIO_Mode = SL2x23_GPIO_R8_Mode; //开漏输出模式
    // GPIO_R8R9_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    // GPIO_Init(SL2x23_GPIO_R8_PORT, &GPIO_R8R9_InitStructure);
    // /* 配置 R9 */
    // GPIO_R8R9_InitStructure.GPIO_Pin = SL2x23_GPIO_R9_PIN;
    // GPIO_R8R9_InitStructure.GPIO_Mode = SL2x23_GPIO_R9_Mode; //开漏输出模式
    // GPIO_Init(SL2x23_GPIO_R9_PORT, &GPIO_R8R9_InitStructure);

    // GPIO_ResetBits( SL2x23_GPIO_R8_PORT, SL2x23_GPIO_R8_PIN );
    // GPIO_ResetBits( SL2x23_GPIO_R9_PORT, SL2x23_GPIO_R9_PIN );

}
#endif

/* SL2823 复位引脚和外部中断引脚配置 */
void SL2x23_RST_INT_EXTI_Config(void)
{
    // GPIO_InitTypeDef  GPIO_InitStructure;
    // EXTI_InitTypeDef EXTI_InitStructure;
    // NVIC_InitTypeDef NVIC_InitStructure;
    
    // /* 开启 RST IRQ 引脚端口时钟 */
    // RCC_APB2PeriphClockCmd(SL2x23_GPIO_RST_CLK | SL2x23_GPIO_IRQ_CLK, ENABLE);
    
    // /* 配置 RST 引脚 */
    // GPIO_InitStructure.GPIO_Pin = SL2x23_GPIO_RST_PIN;
    // GPIO_InitStructure.GPIO_Mode = SL2x23_GPIO_RST_Mode;
    // GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    // GPIO_Init(SL2x23_GPIO_RST_PORT, &GPIO_InitStructure);
    // /* 配置 IRQ 引脚 */
    // GPIO_InitStructure.GPIO_Pin = SL2x23_GPIO_IRQ_PIN;
    // GPIO_InitStructure.GPIO_Mode = SL2x23_GPIO_IRQ_Mode; //配置IRQ为上拉输入
    // GPIO_Init(SL2x23_GPIO_IRQ_PORT, &GPIO_InitStructure);


    // /* 开启复用时钟后在配置EXTI */
    // SL2x23_IRQ_EXTI_CLK_FUN ( SL2x23_IRQ_EXTI_CLK, ENABLE );

    // /* 配置NVIC为优先级组 */
    // NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
    // NVIC_InitStructure.NVIC_IRQChannel = SL2x23_IRQ_EXTI_IRQ;
    // NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
    // NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
    // NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    // NVIC_Init(&NVIC_InitStructure);

    // /* 选择EXTI的信号源 */
    // GPIO_EXTILineConfig(SL2x23_IRQ_EXTI_PORTSOURCE, SL2x23_IRQ_EXTI_PINSOURCE);
    
    // /* 清零标志位 */
    // EXTI_ClearITPendingBit(SL2x23_IRQ_EXTI_LINE);      // clean irq flag
    
    // EXTI_InitStructure.EXTI_Line = SL2x23_IRQ_EXTI_LINE;
    // /* EXTI为中断模式 */
    // EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
    // /* 中断触发信号 */
    // EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; //下降沿
    // /* 使能中断 */	
    // EXTI_InitStructure.EXTI_LineCmd = ENABLE;
    // EXTI_Init(&EXTI_InitStructure);
}

volatile uint8_t irq_flag_io;
/* IRQ引脚 外部中断服务函数 */
void SL2x23_IRQPin_IRQHandler(void)
{
    // /* data interrupt */
    // if(EXTI_GetITStatus(SL2x23_IRQ_EXTI_LINE) == SET)
    // {
    //     irq_flag_io = 1;  /* 标志位置1 然后回到主循环处理-读卡 */
    //     EXTI_ClearITPendingBit(SL2x23_IRQ_EXTI_LINE);      // clean irq flag
    // }
}



void delay_1ms(uint32_t delay_time){

    LOS_Msleep(delay_time);
    #ifdef USE_STDPERIPH_DRIVER
        delay_ms(delay_time);
    #else
    #endif
}

void write_reg(uint8_t addr, uint8_t RegValue) 
{
    /************************************************************************************************************************
    *       寄存器地址小于0x3F的寄存器为通用寄存器，基本与RC523兼容，地址大于0x3F的寄存器为SL2823专用寄存器，为SL2823特有   *
    *       为了保证替换其它芯片时专用寄存器不会被误操作，SL2823中使用0x3F寄存器的值来控制对通用寄存器和专用寄存器的访问    *
    *       – 当0x3F的值为0x0时，只能操作通用寄存器，专用寄存器无法访问                                                     *
    *       – 当0x3F的值为0x1或0x2时，只能操作专用寄存器，通用寄存器无法访问。                                              *
    *       如果需要配置的寄存器地址大于0x3f且小于0x80，需要先将地址0x3f配置为1；配置完成后再将0x3f写回0；                  *
    *       如果需要配置的寄存器地址大于0x7f，需要先将地址0x3f配置为2，配置完成后再将0x3f写回0；举例如下：                  *    
    ************************************************************************************************************************/
    
    #if defined IIC_Mode
    
        i2c_write_word(SL2x23_DEV_ADDRESS, SpecialReg, 0);
        // DWT_DELAY_MS(2);
        delay_1ms(2);
        if((addr>SpecialReg)&&(addr<0x80))
        {
            i2c_write_word(SL2x23_DEV_ADDRESS, SpecialReg, 1);
        }
        if(addr>0x7f)
        {
            i2c_write_word(SL2x23_DEV_ADDRESS, SpecialReg, 2);
        }
        i2c_write_word(SL2x23_DEV_ADDRESS, addr, RegValue);
        if(addr>SpecialReg)
        {
            i2c_write_word(SL2x23_DEV_ADDRESS, SpecialReg, 0);
        }
    #elif defined UART_Mode
        uart1_wrreg((pecialReg&0x3f), 0);
        // DWT_DELAY_MS(2);
        delay_1ms(2);
        if((addr>SpecialReg)&&(addr<0x80))
        {
            uart1_wrreg((pecialReg&0x3f), 1);
        }
        if(addr>0x7f)
        {
            uart1_wrreg((pecialReg&0x3f), 2);
        }
        addr = addr & 0x3f;      //code the first byte
        uart1_wrreg(addr, RegValue);
        if(addr>SpecialReg)
        {
            uart1_wrreg((pecialReg&0x3f), 0);
        }
    #else
        // DWT_DELAY_MS(2);
        delay_1ms(2);
        addr = ((addr & 0x3f) << 1) & 0x7F;     //code the first byte
        #ifdef USE_STDPERIPH_DRIVER
        DEV_WriteSR(addr, RegValue);
        #else
        //接口函数
        #endif
    #endif
}

uint8_t read_reg(uint8_t addr)
{
    #if defined IIC_Mode
        uint8_t reg_value;
        i2c_write_word(SL2x23_DEV_ADDRESS, SpecialReg, 0);
        // DWT_DELAY_MS(2);
        delay_1ms(2);
        if((addr>SpecialReg)&&(addr<0x80))
        {
            i2c_write_word(SL2x23_DEV_ADDRESS, SpecialReg, 1);
        }
        if(addr>0x7f)
        {
            i2c_write_word(SL2x23_DEV_ADDRESS, SpecialReg, 2);
        }
        i2c_read_word(SL2x23_DEV_ADDRESS, addr, &reg_value);
        if(addr>SpecialReg)
        {
            i2c_write_word(SL2x23_DEV_ADDRESS, SpecialReg, 0);
        }
        return reg_value;
    #elif defined UART_Mode
        addr = (addr & 0x3f) | 0x80;    //code the first byte
        uart1_rdreg(addr);
    #else       
        // DWT_DELAY_MS(2);
        delay_1ms(2);
        addr = ((addr & 0x3f) << 1) | 0x80;     //code the first byte
        #ifdef USE_STDPERIPH_DRIVER
        return DEV_ReadSR(addr);
        #endif
    #endif
}

/**
 * @brief  PCB模块与主控通信测试
 * @param  无
 * @retval 无
 */
void spi_wr_test(void) 
{
    int ok = 0;
    uint8_t err = 0;
    int i = 0;
    uint8_t ret = 0xff;
    pcd_reset();//lpcd模式，下直接更新固件。不发reset，spi测试不成功
    delay_1ms(1);
    for(i = 0; i < 100; i++) 
    {
        write_reg(FIFODataReg, i);
        ret = read_reg(FIFODataReg);
        if(i != ret) 
        {
            err++;
            printf("i = 0x%x,errnum = 0x%x, data=0x%x\r\n", i, err, ret);
        } 
        else 
        {
            ok++;
        }
    }
    if(ok == 100) 
    {
        #if defined IIC_Mode
            printf("芯片版本号为: 0x%x\r\n",read_reg(VersionReg));
//            printf("iic test pass! chip id = 0x%x\r\n",read_reg(VersionReg));
        #else
            printf("芯片版本号为: 0x%x\r\n",read_reg(VersionReg));
//            printf("spi test pass! chip id = 0x%x\r\n",read_reg(VersionReg));
        #endif
    } 
    else 
    {
        #if defined IIC_Mode
            printf("模块未连接\r\n");
//            printf("iic test fail!\r\n");
        #else
            printf("模块未连接\r\n");
//            printf("spi test fail!\r\n");
        #endif
    }
    
}
